<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="824.41">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #bf0000}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica}
p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}
p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #000000; min-height: 12.0px}
p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #000000}
p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
span.s1 {color: #000000}
span.s2 {color: #bf0000}
span.s3 {color: #0000bf}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1">//SLUGens released under the GNU GPL as extensions for SuperCollider 3, by Nick Collins, http://www.informatics.sussex.ac.uk/users/nc81/</p>
<p class="p2"><b></b><br></p>
<p class="p3"><b>NL2<span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span> Arbitrary Non Linear Filter Equation</b></p>
<p class="p2"><b></b><br></p>
<p class="p4"><b>NL.ar(input, bufnuma, bufnumb, guard1, guard2, mul, add)</b></p>
<p class="p5"><br></p>
<p class="p4">Represents the arbitrary non-linear filter difference equation in the time domain:</p>
<p class="p5"><br></p>
<p class="p4">y(n) = sum over terms of<span class="Apple-converted-space">      </span>constant * product of x terms at individual powers * product of y terms at individual powers</p>
<p class="p5"><br></p>
<p class="p4">This allows arbitrary crossterms in x and y, but is expensive to calculate.<span class="Apple-converted-space"> </span></p>
<p class="p5"><br></p>
<p class="p4">Stability is definitely not guaranteed; most equations will quickly blow-up. See the guard arguments below. It is recommended that you stick to positive exponents for signals which are within -1 to 1, else explosion of values is inevitable.<span class="Apple-converted-space"> </span></p>
<p class="p6"><br></p>
<p class="p1"><span class="s1">(0.1)**(-1.26)<span class="Apple-converted-space">  </span></span>//negative exponents cause blowup for smaller signals abs(sig) &lt; 1.0</p>
<p class="p5"><br></p>
<p class="p1"><span class="s1">(1.1)**(2.26)<span class="Apple-converted-space">  </span></span>//positive exponents cause blowup for larger signals abs(sig) &gt; 1.0</p>
<p class="p5"><br></p>
<p class="p4">You need to pass in the parameters via two buffers, of arbitrary size.</p>
<p class="p5"><br></p>
<p class="p4"><b>input</b>- What do you want to filter?</p>
<p class="p4"><b>bufnum- </b>A single buffer containing numcrossterms in the first index, then the specification of crossterms as (constant, num x terms, list of x index/exponent pairs, num y terms, list of y index/coefficient pairs). Buffer contents can be switched at run-time as longas this data format is strictly adherred to.<span class="Apple-converted-space"> </span></p>
<p class="p4"><b>maxasize</b>- Maximum index stored for previous outputs</p>
<p class="p4"><b>maxbsize</b>- Maximum index stored for previous inputs</p>
<p class="p4"><b>guard1</b>-<span class="Apple-converted-space">  </span>Watch out for blow-up and reset if necessary; this is the value of the maximum absolute output allowed.<span class="Apple-converted-space"> </span></p>
<p class="p4"><b>guard2</b>-<span class="Apple-converted-space">  </span>Watch out for blow-up and reset if necessary; this is the value of the maximum absolute change of output allowed.<span class="Apple-converted-space"> </span></p>
<p class="p5"><br></p>
<p class="p4"><span class="Apple-converted-space"> </span>On discovering blow-up, filter output is set back to zero for all stored outputs, so that feedback cannot occur. <span class="Apple-converted-space"> </span></p>
<p class="p5"><br></p>
<p class="p7"><br></p>
<p class="p8">(</p>
<p class="p8">a=[2, <span class="Apple-converted-space">  </span>0.5, 1, 0, 1,<span class="Apple-converted-space">  </span>0, <span class="Apple-converted-space">  </span>-0.35, 0, 2, 5, 2, 3, 0.5]; <span class="s2">//specification of crossterms</span></p>
<p class="p8">c=<span class="s3">Buffer</span>.sendCollection(s, a, 1);</p>
<p class="p8">)</p>
<p class="p7"><br></p>
<p class="p8">{<span class="s3">SinOsc</span>.ar(<span class="s3">MouseX</span>.kr(440,1760),0,0.2)}.play <span class="s2">//without</span></p>
<p class="p7"><br></p>
<p class="p1">//subtle distortion</p>
<p class="p8">{<span class="s3">NL2</span>.ar(<span class="s3">SinOsc</span>.ar(<span class="s3">MouseX</span>.kr(440,1760),0,0.5),c,1, 6).clip2(1.0)}.play <span class="s2">//with</span></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p1">//random buffers</p>
<p class="p8">(</p>
<p class="p8">a=[10]++(<span class="s3">Array</span>.fill(10,{<span class="s3">var</span> bsize, asize; bsize= rrand(1,3); asize=rrand(0,3);<span class="Apple-converted-space"> </span></p>
<p class="p7"><br></p>
<p class="p8">[0.5.rand2,bsize]++(<span class="s3">Array</span>.fill(bsize,{[rrand(0,20), exprand(0.1,6)]}).flatten) ++ [asize] ++ (<span class="s3">Array</span>.fill(asize,{[rrand(0,20), exprand(0.1,6)]}).flatten);</p>
<p class="p7"><br></p>
<p class="p8">}).flatten);</p>
<p class="p1"><span class="s1"><span class="Apple-converted-space"> </span></span>//feedback coefficients</p>
<p class="p8">c=<span class="s3">Buffer</span>.sendCollection(s, a, 1);</p>
<p class="p8">)</p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p8">{<span class="s3">NL2</span>.ar(<span class="s3">AudioIn</span>.ar(1),c,21,21).clip2(1.0)}.play <span class="s2">//with</span></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p1">//WARNING; CAN BE VERY CPU EXPENSIVE AND NOISY!</p>
<p class="p8">(</p>
<p class="p1">//limited update</p>
<p class="p8">r= {</p>
<p class="p7"><br></p>
<p class="p8"><span class="s3">inf</span>.do{</p>
<p class="p8"><span class="s3">var</span> e;<span class="Apple-converted-space"> </span></p>
<p class="p8"><span class="s3">var</span> num;<span class="Apple-converted-space"> </span></p>
<p class="p7"><br></p>
<p class="p8">num=rrand(2,10);</p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p8">e=[num]++(<span class="s3">Array</span>.fill(num,{<span class="s3">var</span> bsize, asize; bsize= rrand(1,3); asize=rrand(0,3);<span class="Apple-converted-space"> </span></p>
<p class="p7"><br></p>
<p class="p8">[0.5.rand2,bsize]++(<span class="s3">Array</span>.fill(bsize,{[rrand(0,20), exprand(0.1,6)]}).flatten) ++ [asize] ++ (<span class="s3">Array</span>.fill(asize,{[rrand(0,20), exprand(0.1,6)]}).flatten);</p>
<p class="p7"><br></p>
<p class="p8">}).flatten);</p>
<p class="p7"><br></p>
<p class="p8">if(e.size&lt;=a.size,{</p>
<p class="p7"><br></p>
<p class="p8">c.sendCollection(e);</p>
<p class="p8">});</p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p8">1.0.wait;</p>
<p class="p8">}</p>
<p class="p8">}.fork;<span class="Apple-converted-space"> </span></p>
<p class="p8">)</p>
<p class="p7"><br></p>
<p class="p8">r.stop;</p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p1">//larger sparse arrays; some may lead to silence</p>
<p class="p8">(</p>
<p class="p8">a=[10]++(<span class="s3">Array</span>.fill(10,{<span class="s3">var</span> bsize, asize; bsize= rrand(1,2); asize=rrand(0,1);<span class="Apple-converted-space"> </span></p>
<p class="p7"><br></p>
<p class="p8">[0.7.rand2,bsize]++(<span class="s3">Array</span>.fill(bsize,{[rrand(0,999), exprand(0.1,6)]}).flatten) ++ [asize] ++ (<span class="s3">Array</span>.fill(asize,{[rrand(0,999), exprand(0.1,6)]}).flatten);</p>
<p class="p7"><br></p>
<p class="p8">}).flatten);</p>
<p class="p1"><span class="s1"><span class="Apple-converted-space"> </span></span>//feedback coefficients</p>
<p class="p8">c=<span class="s3">Buffer</span>.sendCollection(s, a, 1);</p>
<p class="p8">)</p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p8">{<span class="s3">NL2</span>.ar(<span class="s3">AudioIn</span>.ar(1),c,1000,1000).clip2(1.0)}.play <span class="s2">//with</span></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p8">(</p>
<p class="p8"><span class="s3">var</span> e;<span class="Apple-converted-space"> </span></p>
<p class="p8"><span class="s3">var</span> num;<span class="Apple-converted-space"> </span></p>
<p class="p7"><br></p>
<p class="p8">num=rrand(2,10);</p>
<p class="p7"><br></p>
<p class="p9"><span class="s1">e=[num]++(</span><span class="s3">Array</span><span class="s1">.fill(num,{</span><span class="s3">var</span> bsize, asize; bsize= rrand(1,2); asize=rrand(0,1);<span class="Apple-converted-space"> </span></p>
<p class="p6"><br></p>
<p class="p9">[0.7.rand2,bsize]++(<span class="s3">Array</span>.fill(bsize,{[rrand(0,999), exprand(0.1,6)]}).flatten) ++ [asize] ++ (<span class="s3">Array</span>.fill(asize,{[rrand(0,999), exprand(0.1,6)]}).flatten);</p>
<p class="p6"><br></p>
<p class="p8">}).flatten);</p>
<p class="p7"><br></p>
<p class="p8">if(e.size&lt;=a.size,{</p>
<p class="p7"><br></p>
<p class="p8">c.sendCollection(e);</p>
<p class="p8">});</p>
<p class="p7"><br></p>
<p class="p8">)</p>
<p class="p7"><br></p>
</body>
</html>
